package rmi;




import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Timer;

import document.DocInfo;
import document.DocPermissions;

import realtime.SendDocumentState;



import messagepasser.DocListDAOSQL;

import messagepasser.DocReadDAOSQL;
import messagepasser.LoginDAOSQL;
import messagepasser.PermissionsDAOSQL;
import messagepasser.UserInfo;
import messagepasser.UserInfoDAOSQL;

public class Server_Servant extends UnicastRemoteObject implements Server {

	Map <Integer, Client> onlineUsers = new HashMap <Integer, Client>();
	HeartBeat hb;
	Server s;

	public Server_Servant(String serverType, String ip) throws RemoteException {

		// start the heartbeat
		Timer t = new Timer();
		hb = new HeartBeat(onlineUsers, t, serverType, ip);
		t.schedule(hb, 10000, 5000);

	}	
	public UserInfo login (String user, String pwd, String ipAddr, int port) throws RemoteException {
		UserInfo userInformation = null;
		LoginDAOSQL logindao = new LoginDAOSQL("com.mysql.jdbc.Driver","jdbc:mysql:///tecbox","userprofile");
		String pwddb = logindao.getPwd(user);
		if(pwddb!=null){
			if (pwddb.equals(pwd)){ 
				System.out.println("Login Successful");
				int userid = logindao.getUserID(user);
				userInformation = new UserInfo(userid, user, true, ipAddr, port);
				logindao.setIpPort(ipAddr, port, userid);
			}
			else {
				System.out.println("Login Successful");
			}
		}
		else {
			System.out.println("Login Unsuccessful");
			return null;
		}

		Set <Integer> userIDs = onlineUsers.keySet();
		for (Integer i : userIDs) {
			try {
				onlineUsers.get(i).newUserOnline(userInformation);
			}
			catch (Exception e) {
				//onlineUsers.remove(i);
				System.out.println ("user may be offline");
			}
		}

		return userInformation; 			

	}

	public List<DocInfo> getDocuments(int userId) throws RemoteException {

		DocListDAOSQL docDAO = new DocListDAOSQL("com.mysql.jdbc.Driver","jdbc:mysql:///tecbox","document");
		return docDAO.getDocsInfo(userId);

	}

	public List<UserInfo> getonlineUsers(int userId) throws RemoteException {
		// TODO Auto-generated method stub
		UserInfoDAOSQL userDAO = new UserInfoDAOSQL("com.mysql.jdbc.Driver","jdbc:mysql:///tecbox","userprofile");
		return (new ArrayList<UserInfo>(Arrays.asList(userDAO.getuserinfo(userId))));
	}

	@Override
	public void register(Client c, int userId) throws RemoteException {
		this.onlineUsers.put(userId, c);
	}

	@Override
	public DocPermissions[] getDocUsers(int docId) throws RemoteException {
		PermissionsDAOSQL perDAO = new PermissionsDAOSQL("com.mysql.jdbc.Driver","jdbc:mysql:///tecbox","user");
		return perDAO.getDocCollaborators(docId);

	}

	@Override
	public void logout(UserInfo user) throws RemoteException {

		LoginDAOSQL logindao = new LoginDAOSQL("com.mysql.jdbc.Driver","jdbc:mysql:///tecbox","userprofile");
		logindao.removeIpPort(user.getUserid());
		onlineUsers.remove(user.getUserid());
		System.out.println ("user offline request");

		Iterator<Integer> r_main = onlineUsers.keySet().iterator();

		while(r_main.hasNext()) {
			int id = r_main.next();
			try {
				onlineUsers.get(id).userOffline(id);
			}
			catch (Exception e) {
				System.out.println ("user may be offline");
			}
		}

	}
	@Override

	//added for client req or chat
	public void regForChat(UserInfo src,UserInfo dest, String type) throws RemoteException {
		
		if (type.equals("text")) {
			onlineUsers.get(src.getUserid()).acceptRequest(dest);
			onlineUsers.get(dest.getUserid()).acceptRequest(src);
		}
		else {
			onlineUsers.get(src.getUserid()).startVoiceChatReceiver(dest);
			onlineUsers.get(dest.getUserid()).startVoiceChatReceiver(src);
			onlineUsers.get(src.getUserid()).startVoiceChatTx(dest);
			onlineUsers.get(dest.getUserid()).startVoiceChatTx(src);
		}
	}

	@Override
	public void syncClients(Map<Integer, Client> onlineUsers) throws RemoteException{

		Iterator<Integer> r_main = onlineUsers.keySet().iterator();

		while(r_main.hasNext()) {
			int id = r_main.next();
			if (this.onlineUsers.get(id) == null) {
				this.onlineUsers.put(id, onlineUsers.get(id));
			}
		}

	}

	public int createDoc ( int userid, String docname, String desc ) throws RemoteException{
		DocListDAOSQL docDAO = new DocListDAOSQL("com.mysql.jdbc.Driver","jdbc:mysql:///tecbox","document");
		Calendar calendar = Calendar.getInstance();
		SimpleDateFormat s1 = new SimpleDateFormat("MM/dd/yy"); // For current date
		String loc = "C:\\abhi\\"+userid+"\\"+docname+".txt";
		int newdocid = docDAO.insertDoc( docname, desc, s1.format(calendar.getTime()), userid, loc);
		return newdocid;
	}


	public void saveDoc(int userid, int docid, String contents) throws RemoteException{
		DocReadDAOSQL docread = new DocReadDAOSQL("com.mysql.jdbc.Driver","jdbc:mysql:///tecbox","document");
		//Check if the user is allowed to edit it or not
		PermissionsDAOSQL permdao = new PermissionsDAOSQL("com.mysql.jdbc.Driver","jdbc:mysql:///tecbox","permissions");
		String perm = permdao.getPerm(userid, docid);
		if(perm==null)
			return;
		if(perm.equalsIgnoreCase("readonly")){
			System.out.println("Not Enough Privilieges");
			return;
		}
		if(perm.equalsIgnoreCase("owner")||perm.equalsIgnoreCase("write")||perm.equalsIgnoreCase("edit")){
			docread.setDocContents(docid,contents);
			System.out.println("Successfully saved");
		}
	}
	public String editdoc(int docid) throws RemoteException{
		DocReadDAOSQL docread = new DocReadDAOSQL("com.mysql.jdbc.Driver","jdbc:mysql:///tecbox","document");
		String str = docread.getDocContents(docid);
		return str;
	}
	public DocPermissions[] shareDoc(int userid, int docid) throws RemoteException{
		PermissionsDAOSQL permissions = new PermissionsDAOSQL("com.mysql.jdbc.Driver","jdbc:mysql:///tecbox","permissions");
		DocPermissions[] docperm = permissions.getDocCollaborators(docid);
		return docperm;
	}
	public void insertPermission(int docid, int userid, String accesstype, int senderId) throws RemoteException{

		Client s = null;
		UserInfo user = null;
		String docName = null;

		PermissionsDAOSQL permissions = new PermissionsDAOSQL("com.mysql.jdbc.Driver","jdbc:mysql:///tecbox","permissions");
		UserInfoDAOSQL userDAO = new UserInfoDAOSQL("com.mysql.jdbc.Driver","jdbc:mysql:///tecbox","user");
		DocListDAOSQL docDAO = new DocListDAOSQL("com.mysql.jdbc.Driver","jdbc:mysql:///tecbox","document");

		permissions.insertPerm(docid,userid,accesstype);

		//Here we can call permissions.getDocCollaborators(docid) to get all the users associated with the doc
		//The notify each of the user of the change in permissions
		DocPermissions[] docperm = permissions.getDocCollaborators(docid);

		user = userDAO.getuser(userid);

		docName = docDAO.getDocName(docid);


		for(int i=0;i<docperm.length;i++){
			s = onlineUsers.get(docperm[i].getUserid());
			if (userid == docperm[i].getUserid()) {
				s.newDocument(docid, docName);
			}
			else {
				s.newDocUser(docid, user);
			}
		}
	}
	public void removePermission(int docid, int userid) throws RemoteException{
		PermissionsDAOSQL permissions = new PermissionsDAOSQL("com.mysql.jdbc.Driver","jdbc:mysql:///tecbox","permissions");
		permissions.removePerm(docid,userid);
	}
	//Create new User
	public Boolean createUser(String username, String fname, String lname, String pwd) throws RemoteException{
		UserInfoDAOSQL userDAO = new UserInfoDAOSQL("com.mysql.jdbc.Driver","jdbc:mysql:///tecbox","userprofile");
		int userid = userDAO.insertUser(username, fname, lname, pwd);
		if(userid>0)
			return true;
		else 
			return false;
	}


}	

